﻿using System;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Input;
using TallyJ1Reporter.ElectionRelated;
using Application = System.Windows.Application;
using Cursors = System.Windows.Input.Cursors;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using MessageBox = System.Windows.MessageBox;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;

namespace TallyJ1Reporter
{
	/// <summary>
	/// Notes
	/// </summary>
	/// <remarks>
	/// 
	/// Key strokes: 
	///    Down/Space/PageDown - move to next name
	///    Up/PageUp - move to previous
	///    B - blank/show display
	/// 
	/// Xml file to load: defined in Settings file
	/// 
	/// 
	/// 
	/// </remarks>
	public partial class MainWindow
	{
		const int TopPadding = 6;
		const int BottomPadding = 5;
		int _currentScreenNum;
		DateTime _lastMouseWheelEvent = DateTime.MinValue;
		ViewState _currentScreenState;
		Point _currentMousePosition;

		public MainWindow()
		{
			InitializeComponent();

			ElectionSource = new ElectionSource();

			SetScreenToState(ViewState.BeforeStarting);

			if (!ElectionSource.FileIsLoaded)
			{

				var btn = MessageBox.Show(ElectionSource.ErrorMessages.Joined("\n") + "\n\n\nSelect a different file?",
				                          Properties.Resources.ApplicationTitle, MessageBoxButton.YesNo, MessageBoxImage.Error);

				if (btn == MessageBoxResult.Yes)
				{
					ElectionSource.AskForNewSourceFile();
				}

				if (!ElectionSource.FileIsLoaded)
				{
					Application.Current.Shutdown();
					return;
				}
			}

			DataContext = ElectionSource;

			ElectionSource.InfoReloaded += InfoSourceOnInfoReloaded;

			PreviewKeyDown += (sender1, keyEventArgs) => HandleKeys(keyEventArgs);
			Tabs.PreviewKeyDown += (o, eventArgs) => HandleKeys(eventArgs);
			GotFocus += (sender, args) =>
			            	{
			            		if (sender is Window)
			            		{
			            			Tabs.Focus();
			            		}
			            	};

			Title = Properties.Resources.ApplicationTitle;
			UpdateApprovalMessage();

			//Cursor = Cursors.None;

			//ShowHintMessage("Ready to Begin");
		}

		protected ElectionSource ElectionSource { get; set; }

		protected override void OnContentRendered(EventArgs e)
		{
			base.OnContentRendered(e);
			//mainContent.RenderTransform.Transform(new Point(0, 0 - 0.2*mainContentHolder.ActualHeight));
			//mainContent.Height = mainContentHolder.ActualHeight*1.4;
		}


		void InfoSourceOnInfoReloaded(object sender, EventArgs eventArgs)
		{
			SetScreenToState(ViewState.BlankedWithMessage);
			DataContext = ElectionSource; // reload??
			UpdateApprovalMessage();
		}

		void UpdateApprovalMessage()
		{
			var approved = ElectionSource.ApprovedForReporting;
			ReportReadyMsg.Text = approved ? "Ready for Reporting!" : "Tellers are still working on it...";
		}


		void HandleKeys(KeyEventArgs keyEvent)
		{
			if (_currentScreenState == ViewState.ShowingNames)
			{
				switch (keyEvent.Key)
				{

				}
			}

			switch (keyEvent.Key)
			{
				case Key.Escape:
					keyEvent.Handled = true;

					if (_currentScreenState == ViewState.BlankedWithMessage)
					{
						Close();
						return;
					}

					SetScreenToState(ViewState.BlankedWithMessage);
					break;

				case Key.F1:
					ShowHelp();
					break;

				case Key.F2:
					DoKeyF2();
					break;

				case Key.I:
					SetScreenToState(ViewState.BlankedWithMessage);
					keyEvent.Handled = true;
					break;

				case Key.P:
					SetScreenToState(ViewState.ShowingPercent);
					keyEvent.Handled = true;
					break;

				case Key.E:
					SetScreenToState(ViewState.ShowingNames);
					keyEvent.Handled = true;
					break;

				default:
					// avoid any wrong keys	
					keyEvent.Handled = true;
					break;
			}

			switch (keyEvent.SystemKey)
			{
				case Key.Right:
					if (IsAltPressed())
					{
						SwitchScreen(keyEvent, 1);
					}

					break;

				case Key.Left:
					if (IsAltPressed())
					{
						SwitchScreen(keyEvent, -1);
					}
					break;
			}
		}

		void DoKeyF2()
		{
			ElectionSource.AskForNewSourceFile();
			SetScreenToState(ViewState.BlankedWithMessage);
		}


		enum ViewState
		{
			BeforeStarting,
			BlankedWithMessage,
			ShowingNames,
			ShowingPercent
		}

		void SetScreenToState(ViewState newState)
		{
			_currentScreenState = newState;
			switch (newState)
			{
				case ViewState.BeforeStarting:
					OnScreenHint.Text = "I = Intro, P = Participation, E = Elected, F1 for more...";

					TabIntro.IsSelected = true;
					break;

				case ViewState.BlankedWithMessage:
					OnScreenHint.Text = "I = Intro, P = Participation, E = Elected, F1 for more...";

					TabIntro.IsSelected = true;
					break;

				case ViewState.ShowingNames:
					HideCursor();

					TabElected.IsSelected = true;
					break;

				case ViewState.ShowingPercent:
					HideCursor();

					TabParticipation.IsSelected = true;

					break;

				default:
					throw new ArgumentOutOfRangeException("newState");
			}
		}

		public void HideCursor()
		{
			Cursor = Cursors.None;
			MouseMove -= OnMouseMove;
			MouseMove += OnMouseMove;
			_currentMousePosition = Mouse.GetPosition(this);
		}

		void OnMouseMove(object sender, MouseEventArgs mouseEventArgs)
		{
			if ((mouseEventArgs.GetPosition(this) - _currentMousePosition).Length > 19)
			{
				Cursor = null;
				MouseMove -= OnMouseMove; // remove this handler for now
			}
		}

		void ShowHelp()
		{
			MessageBox.Show(string.Format(Properties.Resources.QuickHelpText, ElectionSource.SourceFileName),
			                Properties.Resources.ApplicationTitle);
		}

		/// <summary>
		/// Determine which screen to display on. If there is only one, it refreshes the display to 
		/// match the size of the screen.
		/// </summary>
		/// <param name="routedEventArgs"></param>
		/// <param name="i"></param>
		void SwitchScreen(RoutedEventArgs routedEventArgs, int i)
		{
			var screens = Screen.AllScreens;
			if (screens.Length == 1)
				return;


			var newScreen = _currentScreenNum + i;
			if (newScreen > screens.Length - 1)
			{
				newScreen = 0;
			}
			else if (newScreen < 0)
			{
				newScreen = screens.Length - 1;
			}

			_currentScreenNum = newScreen;

			ShowOnScreen(screens[newScreen]);

			routedEventArgs.Handled = true;
		}

		/// <summary>
		/// Fit our display to this screen
		/// </summary>
		/// <param name="screen"></param>
		void ShowOnScreen(Screen screen)
		{
			var bounds = screen.Bounds;

			Hide();
			WindowState = WindowState.Normal;

			Top = bounds.Top;
			Left = bounds.Left;
			Width = bounds.Width;
			Height = bounds.Height;

			WindowState = WindowState.Maximized;
			Show();
		}

		static bool IsAltPressed()
		{
			return (Keyboard.GetKeyStates(Key.LeftAlt) & KeyStates.Down) > 0
			       || (Keyboard.GetKeyStates(Key.RightAlt) & KeyStates.Down) > 0;
		}

	}
}